#include"channel.hpp"
#include"eventloop.hpp"


Channel::Channel(Eventloop *loop, int fd) : _fd(fd), _events(0), _revents(0), _loop(loop)
{
}

// 获取channel对应的fd
int Channel::get_fd()
{
    return _fd;
}

// 获取想要监控的事件
uint32_t Channel::get_events()
{
    return _events;
}

// 设置实际就绪的事件
void Channel::set_revents(uint32_t events)
{
    _revents = events;
}

// 设置监听事件
// 分为检测当前是否监听可读、可写；设置可读、可写；取消可读、可写；取消全部监听
bool Channel::set_events(Channel::EventState state)
{
    if (state == Able_Read)
        return (_events & EPOLLIN);
    else if (state == Able_Write)
        return (_events & EPOLLOUT);

    switch (state)
    {
    case Be_Read:
        _events |= EPOLLIN;
        break;
    case Be_Write:
        _events |= EPOLLOUT;
        break;
    case Disable_Read:
        _events &= ~EPOLLIN;
        break;
    case Disable_Write:
        _events &= ~EPOLLOUT;
        break;
    case Disable_All:
        _events = 0;
        break;
    }
    _loop->epoll_update(this);
    return true;
}

// 设置channel对应的回调函数
void Channel::set_callback(const EventCallback &cb, Channel::CallBackState state)
{
    switch (state)
    {
    case Read:
        _read_callback = cb;
        break;
    case Write:
        _write_callback = cb;
        break;
    case Error:
        _error_callback = cb;
        break;
    case Close:
        _close_callback = cb;
        break;
    case Every:
        _every_callback = cb;
        break;
    }
}

// 移除监控
void Channel::remove_channel()
{
    return _loop->epoll_remove(this);
}

// 事件处理，连接触发了事件就调用
void Channel::handle_event()
{
    // EPOLLIN:可读取非高优先级数据  EPOLLRDHUP:套接字对端关闭  EPOLLPRI:可读取高优先级数据
    if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
    {
        if (_read_callback)
            _read_callback();
    }
    // EPOLLOUT:普通数据可写
    if (_revents & EPOLLOUT)
    {
        if (_write_callback)
            _write_callback();
    }
    // EPOLLERR:有错误发生
    else if (_revents & EPOLLERR)
    {
        // 一旦出错，就会释放连接，因此要放到前边调用任意回调
        if (_error_callback)
            _error_callback();
    }
    // EPOLLHUP:本端描述符产生一个挂断事件
    else if (_revents & EPOLLHUP)
    {
        if (_close_callback)
            _close_callback();
    }
    // 任意事件被触动都会调用
    if (_every_callback)
        _every_callback();
}
